package checkers3d.logic;

import checkers3d.presentation.GUIButton;
import checkers3d.presentation.GUIButtonRadio;
import checkers3d.presentation.GUIButtonRadioGroup;
import checkers3d.presentation.GUIContainer;
import checkers3d.presentation.GUIPictureBox;
import checkers3d.presentation.GameEngine;
import checkers3d.presentation.IDrawable;
import checkers3d.presentation.IInputObserver;
import checkers3d.presentation.UtilGUI;
import java.awt.Point;
import java.util.LinkedList;
import java.util.Random;

/**
 * Displays a window to allow players to pick the type of game that they will
 * play. Allows them to select the board size, the board count, the setup
 * method, and the rules. Based on the user's choices a PlayingSurface will be
 * built randomly or a window for manually placing pieces will be displayed.
 *
 * @author Ruben Acuna
 */
public class MenuGameSetup extends GUIContainer
{
    /**
     * Y axis value along which buttons will be centered.
     */
    private final int CONTROL_BUTTON_AXIS = GameEngine.WINDOW_SIZE.y - 100;

    /**
     * The location where the RadioButtonGroup for board size is.
     */
    private final Point BOARD_SIZE = new Point ((GameEngine.WINDOW_SIZE.x - 600) / 2 + 20, 200); //220
    
    /**
     * The location where the RadioButtonGroup for board count is.
     */
    private final Point BOARD_COUNT = new Point ((GameEngine.WINDOW_SIZE.x - 600) / 2 + 120, 200);

    /**
     * The location where the RadioButtonGroup for setup method is.
     */
    private final Point SETUP_METHOD = new Point ((GameEngine.WINDOW_SIZE.x - 600) / 2 + 220, 200);

    /**
     * The location where the RadioButtonGroup for rule selection is.
     */
    private final Point RULE_TYPE = new Point ((GameEngine.WINDOW_SIZE.x - 600) / 2 + 320, 200);

    /**
     * The location where the RadioButtonGroup for coin toss is.
     */
    private final Point COIN_TOSS = new Point ((GameEngine.WINDOW_SIZE.x - 600) / 2 + 420, 200);

    /**
     * A RadioButtonGroup for the board size buttons.
     */
    GUIButtonRadioGroup sizeGroup = new GUIButtonRadioGroup("Board size:", BOARD_SIZE, this);
    /**
     * Button for 6x6 board.
     */
    GUIButtonRadio sizeSix = new GUIButtonRadio("6x6");
    /**
     * Button for 8x8 board.
     */
    GUIButtonRadio sizeEight = new GUIButtonRadio("8x8");
    /**
     * Button for 12x12 board.
     */
    GUIButtonRadio sizeTen = new GUIButtonRadio("10x10");

    /**
     * A RadioButtonGroup for the board count buttons.
     */
    GUIButtonRadioGroup boardGroup = new GUIButtonRadioGroup("Boards:", BOARD_COUNT, this);
    /**
     * Button for one board.
     */
    GUIButtonRadio boardOne = new GUIButtonRadio("1");
    /**
     * Button for two board.
     */
    GUIButtonRadio boardTwo = new GUIButtonRadio("2");
    /**
     * Button for three board.
     */
    GUIButtonRadio boardThree = new GUIButtonRadio("3");
    /**
     * Button for four board.
     */
    GUIButtonRadio boardFour = new GUIButtonRadio("4");

    /**
     * A RadioButtonGroup for the piece placement buttons.
     */
    GUIButtonRadioGroup placementGroup = new GUIButtonRadioGroup("Placement:", SETUP_METHOD, this);
    /**
     * Button for user piece placement.
     */
    GUIButtonRadio placementUser = new GUIButtonRadio("User");
    /**
     * Button for random piece placement.
     */
    GUIButtonRadio placementRandom = new GUIButtonRadio("Random");

    /**
     * A RadioButtonGroup for the rule selection buttons.
     */
    GUIButtonRadioGroup ruleGroup = new GUIButtonRadioGroup("Rules:", RULE_TYPE, this);
    
    /**
     * Button for normal checkers rules (checker, king, kingify).
     */
    GUIButtonRadio ruleNormal = new GUIButtonRadio("Normal");
    /**
     * Button for extended checkers rules (all available pieces).
     */
    GUIButtonRadio ruleExtended = new GUIButtonRadio("Extended");

    /**
     * A RadioButtonGroup for the coin toss buttons.
     */
    GUIButtonRadioGroup tossGroup = new GUIButtonRadioGroup("First Player:", COIN_TOSS, this);

   /**
     * Button for making the visitor go first.
     */
    GUIButtonRadio tossForceHome;
    /**
     * 
     * Button for making home go first.
     */
    GUIButtonRadio tossForceVisitor;
    /**
     * Button for random player to go first.
     */
    GUIButtonRadio tossCoin;

    /**
     * Home player.
     */
    Player home;
    /**
     * Visiting player.
     */
    Player visitor;

    /**
     * Creates a window with buttons for selection of board size, board count,
     * piece placement method, and rule selection. Options are displayed as
     * ButtonRadios so the player must make a choice from each category. A
     * button also exists to start the game with the choices made and it either
     * adds a game directly to the render stack (random placement) or opens a 
     * new window for piece placement.
     *
     * @param size The size in pixels of this GUIContainer.
     */
    public MenuGameSetup(Point size, Player home, Player visitor)
    {
        super(size);

        this.home = home;
        this.visitor = visitor;

        LinkedList<IDrawable> buttons = new LinkedList<IDrawable>();

        //add the background
        add(new GUIPictureBox("background.png", new Point (0, 0)));

        //add the start button with behavior.
        buttons.add(new GUIButton("button-start.png", null, new ObserverStart()));

        //create the return button with behavior.
        buttons.add(new GUIButton("button-return.png", null, new ObserverReturn()));

        //add the buttons to the GUIContainer.
        for(IDrawable component : buttons)
            add(component);

        //compute the positions of the button
        UtilGUI.computeLayoutSpanning(getSize(), CONTROL_BUTTON_AXIS, buttons);

        //create the radio buttons and titles for coin toss selection.
        tossForceHome = new GUIButtonRadio(home.getName() + " as home and " + visitor.getName() + " as visitor.");
        tossForceVisitor = new GUIButtonRadio(visitor.getName() + " as home and " + home.getName() + " as visitor.");
        tossCoin = new GUIButtonRadio("Coin toss");

        //radio button groups to GUIContainer.
        add(sizeGroup);
        add(boardGroup);
        add(placementGroup);
        add(ruleGroup);
        add(tossGroup);

        //add radio buttons to groups.
        sizeGroup.add(sizeSix);
        sizeGroup.add(sizeEight);
        sizeGroup.add(sizeTen);
        boardGroup.add(boardOne);
        boardGroup.add(boardTwo);
        boardGroup.add(boardThree);
        boardGroup.add(boardFour);
        placementGroup.add(placementUser);
        placementGroup.add(placementRandom);
        ruleGroup.add(ruleNormal);
        ruleGroup.add(ruleExtended);
        tossGroup.add(tossForceHome);
        tossGroup.add(tossForceVisitor);
        tossGroup.add(tossCoin);

        //set default radio buttons.
        sizeEight.setOn();
        boardTwo.setOn();
        placementRandom.setOn();
        ruleExtended.setOn();
        tossForceVisitor.setOn();
    }

    /**
     * Returns a string representation of this object containing it's class name.
     *
     * @return String representation.
     */
    @Override
    public String toString()
    {
        return getClass().getName() + " -> " + sizeGroup + boardGroup
                                             + placementGroup + ruleGroup;
    }

    /**
     * IInputObserver for the start button that creates either the game window
     * or the piece placement window.
     */
    private class ObserverStart implements IInputObserver
    {
        /**
         * Pushes a game object on the render stack using the selected options
         * if random piece placement is selected, otherwise creates a window
         * for manual piece placement.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            //disallow more than two boards when the board is greater than 6x6
            if(!sizeSix.isOn() && (boardFour.isOn() || boardThree.isOn()))
            {
                boardTwo.setOn();
                boardThree.setOff();
                boardFour.setOff();
                return;
            }

            PlayingSurface3D playingSurface3D;

            //set graphics for the home player.
            home.setCheckerRR("player1tokenchecker.png");
            home.setKingRR("player1tokenking.png");
            home.setWallRR("generictokenwall.png");
            home.setSafeRR("player1tokensafe.png");
            home.setMineRR("player1tokenmine.png");

            //set graphics for the visiting player.
            visitor.setCheckerRR("player2tokenchecker.png");
            visitor.setKingRR("player2tokenking.png");
            visitor.setWallRR("generictokenwall.png");
            visitor.setSafeRR("player2tokensafe.png");
            visitor.setMineRR("player2tokenmine.png");

            int boardSize;
            int boardCount;
            boolean extended;

            if(sizeSix.isOn())
                boardSize = 6;
            else if(sizeEight.isOn())
                boardSize = 8;
            else //sizeTen must be on.
                boardSize = 10;

            if(boardOne.isOn())
                boardCount = 1;
            else if(boardTwo.isOn())
                boardCount = 2;
            else if(boardThree.isOn())
                boardCount = 3;
            else //boardFour must be on.
                boardCount = 4;

            if(ruleNormal.isOn())
                extended = false;
            else //ruleExtended must be on.
                extended = true;

            if(tossCoin.isOn())
            {
                Random generator = new Random();

                if(generator.nextBoolean())
                {
                    Player temp = home;
                    home = visitor;
                    visitor = temp;
                }
                //else do nothing since the order is already right.
            }
            else if(tossForceVisitor.isOn())
            {
                    Player temp = home;
                    home = visitor;
                    visitor = temp;
            }
            //do need for an else since we assume tossForceHome in the beginning.

            //remove this menu
            GameMaster.getInstance().removeTopGUIContainer();

            //build the playing surface. Random placement on.
            if(placementRandom.isOn())
            {
                playingSurface3D = GameSetupRandom.getPlayingSurface3D(home, visitor, boardSize, boardSize, boardCount, extended);
                GameMaster.getInstance().addGUIContainer(new Game(home, visitor, playingSurface3D, getSize()));
            }
            //Random place not on so default to user placement.
            else
            {
                playingSurface3D = new PlayingSurface3D(boardSize, boardSize, boardCount);

                //RA: GameSetupUser will create a Game after it is finished.
                GameMaster.getInstance().addGUIContainer(new GameSetupUser(home, visitor, playingSurface3D, extended, getSize()));
            }
        }

        /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }

    /**
     * A observer for a button that returns user to the previous screen.
     */
    private class ObserverReturn implements IInputObserver
    {
        /**
         * Returns the user to the previous screen.
         *
         * @param position Location of click within button.
         */
        public void onClick(Point position)
        {
            GameMaster.getInstance().removeTopGUIContainer();
        }

         /**
         * Key press observer that does nothing.
         *
         * @param key Key that was pressed.
         */
        public void onKeyPress(char key)
        {
            //do nothing.
        }
    }
}